﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using Localization;
using SinBiota.Model.Business.AuthenticationServices.Interfaces;
using SinBiota.Model.Business.PersistenceServices.Interfaces;
using SinBiota.Model.DataTypes;
using SinBiota.Model.Entities;
using SinBiota.Model.Entities.CustomAttributes;
using System.Web.Mvc;
using Sinbiota.Web.Extensions;

namespace Sinbiota.Web.Models
{
    public class OccurrenceFormModel
    {
        // Occurrence:
        [LocalizedName("Occurrence", NameResourceType = typeof(Strings))]
        public Occurrence Occurrence { get; set; }

        // Specimen List
        public SpecimenListModel SpecimenListModel { get; set; }
        // Checkboxes:
        public CheckboxGroup EcosystemCheckboxGroup { get; set; }
        public CheckboxGroup HabitatCheckboxGroup { get; set; }
        public CheckboxGroup MicroHabitatCheckboxGroup { get; set; }

        ////Range is a rectangle that contais Sao Paulo
        //[LocalizedName("Latitude", NameResourceType = typeof(Strings))]
        //[Range(-26,-18, ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = "LatitudeRangeMustBeBetween")] 
        //public long Latitude { get; set; }

        //[Range(-54, -44, ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = "LongitudeRangeMustBeBetween")]
        //[LocalizedName("Longitude", NameResourceType = typeof(Strings))]
        //public long Longitude { get; set; }

    }

    public class OccurrenceDisplayModel
    {

        public OccurrenceDisplayModel(Occurrence occurrence, ITaxonPersistenceServices taxonPersistenceServices, bool canEditOccurrence)
        {
            Id = occurrence.Id;
            UserName = occurrence.User.Name;
            
            // Detais:
            OccurrenceAuthor = occurrence.Author == null ? "" : occurrence.Author.Name;
            Date = String.Format("{0}{1}", occurrence.StartDate,  !string.IsNullOrEmpty(occurrence.EndDate) ? " -- " + occurrence.EndDate : "");
            Method = occurrence.Method == null ? "" : occurrence.Method.Name;
            MethodDescription = occurrence.Method == null ? "" : occurrence.Method.Description;
            Keywords = occurrence.Keywords.Select(x => x.Name);
            FinalRemarks = occurrence.FinalRemarks;
            RelatedOccurrences = occurrence.RelatedOccurrences;
            //Location:
            Municipality = string.Format("{0}, {1}", occurrence.Location.Municipality.Name, occurrence.Location.Municipality.State);
            Location = occurrence.Location.Description;
            Coordinates = String.Format("{0}, {1}",
                occurrence.Location.Latitude.ToString("F",CultureInfo.CreateSpecificCulture("en-US")), 
                occurrence.Location.Longitude.ToString("F",CultureInfo.CreateSpecificCulture("en-US")));
            Ambient = Strings.ResourceManager.GetString(occurrence.Location.Ambient.ToString()); 
            GPSPrecision = occurrence.Location.GPSPrecision;
            LocationPrecision = Strings.ResourceManager.GetString(occurrence.Location.LocationPrecision.ToString());
            LocationExtension = string.Format("{0} {1}", occurrence.Location.LocationExtension, occurrence.Location.LocationExtensionUnit);
            ConservationUnit = occurrence.Location.ConservationUnit == null ? "" : occurrence.Location.ConservationUnit.Name;
            DrainageBasin = occurrence.Location.DrainageBasin == null ? "" : occurrence.Location.DrainageBasin.Name;
            Ecosystem = String.Join(", ", occurrence.Ecosystems.Select(x => x.Name)); 
            Habitat = String.Join(", ", occurrence.Habitats.Select(x => x.Name));
            MicroHabitat = String.Join(", ", occurrence.MicroHabitats.Select(x => x.Name));
            
            // Occurrence autor and project details:
            BibliographicalReference = occurrence.BibliographicalReference == null ? "" : occurrence.BibliographicalReference.Title;
            Institution = occurrence.Author != null ? (occurrence.Author.Institution != null ? occurrence.Author.Institution.Name : "" ) : "";
            OccurrenceAuthorAddress = occurrence.Author.Address;
            Project = occurrence.Project.Name;
            ProjectId = occurrence.Project.Id;
            WebsiteURL = occurrence.Project.WebsiteURL;
            InsertedByUser = string.Format("{0} ({1}) - {2}", occurrence.User.Username, occurrence.User.Email, occurrence.RecordDate);
            
            //specimens and legacy taxonomic groups:
            TaxonomicGroups = occurrence.SpecimenList.Select(t => t.TaxonomicClassification.LegacyTaxonomicGroup).Distinct();
            SpecimenListModel = new SpecimenListFullModel(occurrence.SpecimenList, taxonPersistenceServices);

            // editing:
            CanEditOccurrence = canEditOccurrence;
        }

        public int Id { get; set; }

        [LocalizedName("UserName", NameResourceType = typeof(Strings))]
        public string UserName { get; set; }

        [LocalizedName("OccurrenceAuthor", NameResourceType = typeof(Strings))]
        public string OccurrenceAuthor { get; set; }

        [LocalizedName("Date", NameResourceType = typeof(Strings))]
        public string Date { get; set; }

        [LocalizedName("Method", NameResourceType = typeof(Strings))]
        public string Method { get; set; }

        [LocalizedName("Description", NameResourceType = typeof(Strings))]
        public string MethodDescription { get; set; }

        [LocalizedName("Keywords", NameResourceType = typeof(Strings))]
        public IEnumerable<string> Keywords { get; set; }

        [LocalizedName("FinalRemarks", NameResourceType = typeof(Strings))]
        public string FinalRemarks { get; set; }

        [LocalizedName("RelatedOccurrences", NameResourceType = typeof(Strings))]
        public IList<Occurrence> RelatedOccurrences { get; set; }

        [LocalizedName("Municipality", NameResourceType = typeof(Strings))]
        public string Municipality { get; set; }

        [LocalizedName("Location", NameResourceType = typeof(Strings))]
        public string Location { get; set; }

        [LocalizedName("ConservationUnit", NameResourceType = typeof(Strings))]
        public string ConservationUnit { get; set; }

        [LocalizedName("Ambient", NameResourceType = typeof(Strings))]
        public string Ambient { get; set; }

        [LocalizedName("DrainageBasin", NameResourceType = typeof(Strings))]
        public string DrainageBasin { get; set; }

        [LocalizedName("Coordinates", NameResourceType = typeof(Strings))]
        public string Coordinates { get; set; }

        [LocalizedName("GPSPrecision", NameResourceType = typeof(Strings))]
        public float GPSPrecision { get; set; }

        [LocalizedName("LocationPrecision", NameResourceType = typeof(Strings))]
        public string LocationPrecision { get; set; }

        [LocalizedName("LocationExtension", NameResourceType = typeof(Strings))]
        public string LocationExtension { get; set; }

        [LocalizedName("Ecosystem", NameResourceType = typeof(Strings))]
        public string Ecosystem { get; set; }

        [LocalizedName("Habitat", NameResourceType = typeof(Strings))]
        public string Habitat { get; set; }

        [LocalizedName("MicroHabitat", NameResourceType = typeof(Strings))]
        public string MicroHabitat { get; set; }

        [LocalizedName("Project", NameResourceType = typeof(Strings))]
        public string Project { get; set; }
        public int ProjectId { get; set; }

        [LocalizedName("WebsiteURL", NameResourceType = typeof(Strings))]
        public string WebsiteURL { get; set; }

        [LocalizedName("Address", NameResourceType = typeof(Strings))]
        public string OccurrenceAuthorAddress { get; set; }

        [LocalizedName("Institution", NameResourceType = typeof(Strings))]
        public string Institution { get; set; }

        [LocalizedName("BibliographicalReference", NameResourceType = typeof(Strings))]
        public string BibliographicalReference { get; set; }

        [LocalizedName("InsertedByUser", NameResourceType = typeof(Strings))]
        public string InsertedByUser { get; set; }

        [LocalizedName("TaxonomicGroups", NameResourceType = typeof(Strings))]
        public IEnumerable<LegacyTaxonomicGroup> TaxonomicGroups { get; set; }

        public SpecimenListFullModel SpecimenListModel { get; set; }

        public bool CanEditOccurrence { get; set; }
    }

    public class OccurrenceWithUserPermission
    {
        public Occurrence Occurrence { get; set; }
        public bool IsEditable { get; set; }
    }

    public class OccurrenceListModel : IEnumerable<OccurrenceWithUserPermission>
    {

        public IEnumerable<OccurrenceWithUserPermission> OccurrenceWithUserPermissions { get; set; }

        public OccurrenceListModel(IEnumerable<Occurrence> occurrences, IPermissionServices permissionServices, string username)
        {
            OccurrenceWithUserPermissions = occurrences.Select(o => new OccurrenceWithUserPermission { Occurrence = o, IsEditable = permissionServices.CanEditOccurrence(username, o) });
        }

        public IEnumerator<OccurrenceWithUserPermission> GetEnumerator()
        {
            return OccurrenceWithUserPermissions.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    
    public class OccurrenceSearchModel
    {
        public string SearchField { get; set;}
        public OccurrenceSearchOption OccurrenceSearchOption { get; set; }

    }

    public enum OccurrenceSearchOption
    {
        Taxon, Ambient, Author, Publication, TaxonomicGroup, Municipality, Project, ProjectMember,  ProjectCoordinator, Keyword, Username, Id
    }

    

    public class ChooseProjectForm
    {
        //Project
        public ChooseProjectForm(IEnumerable<Project> projects)  
        {
            ProjectList = projects.Distinct().ToSelectListItems(x => x.Name, x => x.Id.ToString(), x => false);
        }

        public IEnumerable<SelectListItem> ProjectList { get; private set; }
        public int ProjectId { get; set; }
        
        
    }

}


